package com.dommettj.rawfix.gui;

import com.dommettj.rawfix.utils.JTextAreaDriver;
import com.objogate.wl.Prober;
import com.objogate.wl.swing.AWTEventQueueProber;
import com.objogate.wl.swing.ComponentSelector;
import com.objogate.wl.swing.driver.*;
import com.objogate.wl.swing.gesture.GesturePerformer;
import com.objogate.wl.swing.matcher.ShowingOnScreenMatcher;

import javax.swing.*;

import static com.objogate.wl.swing.driver.ComponentDriver.named;
import static com.objogate.wl.swing.driver.ComponentDriver.showingOnScreen;
import static com.objogate.wl.swing.matcher.ComponentMatchers.withButtonText;
import static org.hamcrest.Matchers.containsString;

@SuppressWarnings("unchecked")
public class GuiDriver {

    private final Prober prober;
    private final JFrameDriver mainFrameDriver;
    private final JFrameDriver settingsFrameDriver;
    private final JMenuBarDriver menuBarDriver;

    public GuiDriver() {
        prober = new AWTEventQueueProber();
        mainFrameDriver = new JFrameDriver(new GesturePerformer(), prober, named(RawFixMainFrame.MAIN_WINDOW), showingOnScreen());
        settingsFrameDriver = new JFrameDriver(new GesturePerformer(), prober, named(RawFixMenu.SETTINGS_WINDOW), showingOnScreen());
        menuBarDriver = new JMenuBarDriver(mainFrameDriver, named(RawFixMenu.MENU_BAR));
    }

    public void dispose() {
        mainFrameDriver.dispose();
        closeSettingsIfNecessary();
    }

    private void closeSettingsIfNecessary() {

        try {
            settingsFrameDriver.component().component().isShowing();
            settingsFrameDriver.dispose();
        } catch(IndexOutOfBoundsException e) {
            //window is not showing
        }
    }

    public void logon() {
        button(RawFixMainFrame.LOGON_BUTTON, mainFrameDriver).click();
        pause(500);
    }

    public void logoff() {
        button(RawFixMainFrame.LOGOFF_BUTTON, mainFrameDriver).click();
    }

    public void logBoxContains(final String expectedString) {
        display().hasText(containsString(expectedString));
    }

    public void openSettings() {

        final JMenuDriver menu = menuBarDriver.menu(withButtonText("Settings"));
        final ComponentSelector<JMenu> selector = menu.component();
        prober.check(selector);
        menu.leftClickOnComponent();
        menu.isShowing();

        final JMenuItemDriver item = menu.menuItem(withButtonText("Change Settings"));
        final ComponentSelector<JMenuItem> itemSelector = item.component();
        prober.check(itemSelector);
        item.leftClickOnComponent();

        pause(500);
    }

    public void saveSettings() {
        button(RawFixMenu.SAVE_BUTTON, settingsFrameDriver).click();
    }

    public void hostSettingEquals(final String host) {
        settingsTextField(RawFixMenu.HOST_FIELD).hasText(host);
    }

    public void enterHost(final String host) {
        enterText(host, RawFixMenu.HOST_FIELD);
    }

    public void enterPort(final String port) {
        enterText(port, RawFixMenu.PORT_FIELD);
    }

    public void enterSenderCompId(final String senderCompId) {
        enterText(senderCompId, RawFixMenu.SENDER_FIELD);
    }

    public void enterTargetCompId(final String targetCompId) {
        enterText(targetCompId, RawFixMenu.TARGET_FIELD);
    }

    public void portSettingEquals(final String host) {
        settingsTextField(RawFixMenu.PORT_FIELD).hasText(host);
    }

    public void senderCompIdSettingEquals(final String host) {
        settingsTextField(RawFixMenu.SENDER_FIELD).hasText(host);
    }

    public void targetCompIdSettingEquals(final String host) {
        settingsTextField(RawFixMenu.TARGET_FIELD).hasText(host);
    }

    private void enterText(final String text, final String fieldName) {
        final JTextFieldDriver fieldDriver = settingsTextField(fieldName);
        fieldDriver.focusWithMouse();
        fieldDriver.typeText(text);
    }

    private JButtonDriver button(final String name, final ComponentDriver parentDriver) {
        return new JButtonDriver(parentDriver, JButton.class, ComponentDriver.named(name));
    }

    private JTextAreaDriver display() {
        return new JTextAreaDriver(mainFrameDriver, JTextArea.class, ComponentDriver.named(RawFixMainFrame.LOGBOX_DISPLAY));
    }

    private JTextFieldDriver settingsTextField(final String name) {
        return new JTextFieldDriver(settingsFrameDriver, JTextField.class, ComponentDriver.named(name));
    }

    private void pause(final long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
